package com.crcode.crm.service.module.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.crcode.crm.bean.module.ModuleBean;
import com.crcode.crm.dao.module.ModuleDao;
import com.crcode.crm.service.module.ModuleService;
import com.crcode.crm.utils.PageVo;
import com.crcode.crm.utils.ResultPageUtil;
import com.crcode.crm.utils.ResultUtil;

/**
 * 模块业务处理实现层
 * @author lxw
 * @date 2019年1月22日
 */
@Service(value="moduleService")
@Transactional
public class ModuleServiceImpl implements ModuleService {

	@Autowired
	private ModuleDao moduleDao;
	
	@Override
	public ModuleBean getById(Integer serializable) {

		return this.moduleDao.findById(serializable).get();
	}

	@Override
	public ModuleBean saveResultBean(ModuleBean t) {
		
		return this.moduleDao.save(t);
	}

	@Override
	public boolean saveResultBoolean(ModuleBean t) {
		try {
			this.moduleDao.save(t);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public ModuleBean updateResultBean(ModuleBean t) {

		return this.moduleDao.save(t);
	}

	@Override
	public boolean updateResultBoolean(ModuleBean t) {
		try {
			this.moduleDao.save(t);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public boolean delete(Integer serializable) {
		try {
			this.moduleDao.deleteById(serializable);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	@Override
	public List<ModuleBean> getAll() {

		return this.moduleDao.findAll();
	}
	/**
	 * 根据条件分页加载
	 * @author lxw
	 * @date 2018年4月1日 下午2:26:17
	 * @param pid 父级序号
	 * @param pageIndex 当前页
	 * @param pageSize 每页大小
	 * @param name 模块名称
	 * @return
	 */
	@Override
	public ResultPageUtil findBySpec(Map<String, Object> param,PageVo vo) {
		Integer pageIndex = vo.getPageIndex() - 1;
		Pageable pageable =null;
		if(StringUtils.isNotEmpty(vo.getOrderBy())){
			if(vo.getOrderDesc()==1){
				pageable = PageRequest.of(pageIndex, vo.getPageSize(),Direction.DESC, vo.getOrderBy());
			}else if(vo.getOrderDesc()==0){
				pageable = PageRequest.of(pageIndex, vo.getPageSize(),Direction.ASC, vo.getOrderBy());
			}	
		}else{
			pageable = PageRequest.of(pageIndex, vo.getPageSize());
		}
		Page<ModuleBean> page = moduleDao.findAll(spec(param), pageable);
		ResultPageUtil ru = new ResultPageUtil();
		ru.setCurrentPage(vo.getPageIndex());
		ru.setPageSize(vo.getPageSize());
		ru.setTotalPages(page.getTotalPages());
		ru.setRows(page.getContent());
		ru.setTotal(page.getTotalElements());
		return ru;
	}
	
	/**
	 * 创建动态查询条件组合
	 * @author lxw  
	 * @date 2018年8月27日 下午2:59:37
	 * @param module
	 * @return
	 */
    private Specification<ModuleBean> spec(final Map<String, Object> param) {
        Specification<ModuleBean> spec = new Specification<ModuleBean>() {

        	private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<ModuleBean> root, CriteriaQuery<?> criteriaQuery,
					CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<>();
				if (param.get("puuid")!=null) {
					predicates.add(cb.equal(root.get("puuid"),param.get("puuid")));
				}
				if (StringUtils.isNotEmpty(param.get("moduleName").toString())) {
					predicates.add(cb.like(root.get("moduleName"),"%"+param.get("moduleName").toString()+"%"));
				}
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		};
        return spec;
    }

	@Override
	public List<ModuleBean> findDataByPuuidAndModuleName(String puuid, String moduleName) {

		return this.moduleDao.findByPuuidAndModuleName(puuid, moduleName);
	}
    /**
     * 新增OR编辑保存
     * @author lxw
     * @date 2019年1月22日
     * @param module
     * @return
     */
	@Override
	public ResultUtil addOrEditSave(ModuleBean module){
		
		ResultUtil ru = new ResultUtil();
		List<ModuleBean> lm = new ArrayList<>();
		boolean  is = false;
		//新增
		if(module.getId()==null){
			lm = this.moduleDao.findByPuuidAndModuleName(module.getPuuid(), module.getModuleName());
			if(!lm.isEmpty()){
				ru.setInfo("操作失败，同一级下模块名已存在！");
				ru.setObj(null);
				ru.setStatus(false);
				return ru;
			}
			module.setUuid(UUID.randomUUID().toString().replaceAll("-", ""));
			is = this.saveResultBoolean(module);
			ru.setInfo(is?"操作成功！":"操作失败！");
			ru.setObj(module);
			ru.setStatus(is);
			return ru;
		}
		
		//编辑
		lm = this.moduleDao.findByPuuidAndModuleNameAndUuidNot(module.getPuuid(), module.getModuleName(),module.getUuid());
		if(!lm.isEmpty()){
			ru.setInfo("操作失败，同一级下模块名已存在！");
			ru.setObj(null);
			ru.setStatus(false);
			return ru;
		}
		
		ModuleBean oldM = this.moduleDao.findByUuid(module.getUuid());
		oldM.setModuleName(module.getModuleName());
		oldM.setModuleRemarks(module.getModuleRemarks());
		oldM.setModuleType(module.getModuleType());
		oldM.setModuleUrl(module.getModuleUrl());
		oldM.setIcon(module.getIcon());
		is = this.updateResultBoolean(oldM);
		
		ru.setInfo(is?"操作成功！":"操作失败！");
		ru.setObj(module);
		ru.setStatus(is);
		return ru; 
	}
    /**
     * 根据程序序号集删除
     * @author lxw
     * @date 2019年1月22日
     * @param uuids
     * @return
     */
	@Override
	public boolean deleteModulesByUUids(List<String> uuids){
		try {
			this.moduleDao.deleteByUuidIn(uuids);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	/**
	 * 批量删除
	 * @author lxw
	 * @date 2019年2月14日
	 * @param uuids
	 * @return
	 */
	@Override
	public ResultUtil deleteByUUids(String uuids){
		String [] arr = uuids.split(",");
		List<String> ids = new ArrayList<String>();
		for (String str : arr) {
			ids.add(str);
			ids.addAll(this.searchSunUuids(str, new ArrayList<>()));
		}
		boolean is = this.deleteModulesByUUids(ids);
		
		ResultUtil ru = new ResultUtil();
		
		ru .setInfo(is?"操作成功！":"操作失败！");
		ru.setObj(null);
		ru.setStatus(is);
		return ru;
	}
	/**
	 * 查询 子集序号
	 * @author George
	 * @param id
	 * @param rlist
	 * @return
	 */
	public List<String> searchSunUuids(String uuid,List<String> rlist){
		List<String> list = new ArrayList<>();
		list = this.moduleDao.findIdByPuuid(uuid);
		if(list.isEmpty()){
			return rlist;
		}
		for (String sid : list) {
			searchSunUuids(sid,rlist);
			rlist.add(sid);
		}
		return rlist;
	}
	@Override
	public List<ModuleBean> getDataByPuuid(String puuid) {

		return this.moduleDao.findByPuuid(puuid);
	}
	
	/**
	 * 加载模块树
	 * @author lxw  
	 * @date 2018年8月27日 下午4:35:48
	 * @return
	 */
	@Override
	public Map<String, Object> loadModuleTree() {
		Map<String, Object> rm = new HashMap<String, Object>();
		rm.put("id", 0);
		rm.put("uuid", 0);
		rm.put("name", "根节点");
		rm.put("puuid", -100);
		rm.put("level", -100);
		rm.put("children", createAllSubset("0"));
		return rm;
	}

	/**
	 * 创建树 所有节点及子集
	 * @author lxw  
	 * @date 2018年8月27日 下午4:37:34
	 * @param id
	 * @return
	 */
	public List<Map<String, Object>> createAllSubset(String puuid) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		List<ModuleBean> ilist = moduleDao.findByPuuid(puuid);
		if (ilist.isEmpty()) {
			return list;
		}
		for (ModuleBean m : ilist) {
			Map<String, Object> rm = new HashMap<String, Object>();
			rm.put("id", m.getId());
			rm.put("uuid", m.getUuid());
			rm.put("name", m.getModuleName());
			rm.put("puuid", m.getPuuid());
			rm.put("level", m.getModuleLevel());
			rm.put("children", createAllSubset(m.getUuid()));
			list.add(rm);
		}
		return  list;
	}

	@Override
	public List<ModuleBean> getDataByModuleTyoeAndPuuid(Integer moduleType, String puuid) {

		return this.moduleDao.findByModuleTypeAndPuuid(moduleType, puuid);
	}

	@Override
	public List<ModuleBean> getDataByPuuidAndUuidIn(String puuid, List<String> uuids) {

		return this.moduleDao.findByPuuidAndUuidIn(puuid, uuids);
	}
}
